mod proto;

use proto::hello::say_server::*;
// use tonic_health::server::health_reporter;
use tonic::{Status, Response, Request, transport::Server, Code};
use crate::proto::hello::{HelloResponse, HelloRequest};
// use std::env;
// use std::path::PathBuf;
// use std::sync::{Mutex, Arc};
use prost_types::value::Kind;
use serde_json::{Value, Map};



#[tokio::main]
async fn main()-> Result<(), Box<dyn std::error::Error>> {

    // tonic::include_file_descriptor_set!("helloworld_descriptor");

    // let descriptor_file = tokio::fs::read("src/grpc/proto/hello_descriptor.bin").await.unwrap();
    let descriptor_file = include_bytes!("proto/hello_descriptor.bin");
    let reflect_server = tonic_reflection::server::Builder::configure()
        // .include_reflection_service(true)
        // .register_file_descriptor_set()
        .register_encoded_file_descriptor_set(descriptor_file)
        .build().unwrap();

    let say = HelloServer{};
    let say = SayServer::with_interceptor(say,oauth_check);
    Server::builder()
        .concurrency_limit_per_connection(128)
        .timeout(std::time::Duration::from_secs(3))
        .add_service(reflect_server)
        .add_service(say)
        .serve("127.0.0.1:666".parse().unwrap())
        .await?;
    Ok(())
}

pub struct HelloServer{
}


//回调函数，执行注册方法
#[tonic::async_trait]
impl Say for HelloServer{
    async fn say_hello(&self, request: Request<HelloRequest>) -> Result<Response<HelloResponse>, Status> {
        wd_log::log_info_ln!("client request:{}",request.get_ref().value);
        if let Some(ref s) = request.get_ref().content {
            let map = parse_btree_map(s);
            let name = map.get("name").unwrap();
            wd_log::log_debug_ln!("client name is {}",name.to_string());
        }
        let resp = Response::new(
            HelloResponse{value:String::from("hi,i am server"), content: None }
        );
        Ok(resp)
    }
}
fn parse_btree_map(map:&prost_types::Struct) -> Map<String, Value> {
    let mut json_map = serde_json::Map::new();
    for (key,value) in map.fields.iter() {
        let v = value.kind.as_ref().unwrap();
        match v {
            Kind::NullValue(_) => {}
            Kind::NumberValue(n) => {
                json_map.insert(key.clone(),serde_json::Value::Number(serde_json::Number::from_f64(n.clone()).unwrap()));
            }
            Kind::StringValue(s) => {
                json_map.insert(key.clone(),serde_json::Value::String(s.clone()));
            }
            Kind::BoolValue(_) => {}
            Kind::StructValue(_) => {}
            Kind::ListValue(_) => {}
        };
    }
    return json_map
}

//鉴权检查，打印请求id
fn oauth_check(reqs: Request<()>) -> Result<Request<()>, Status>  {
    let reqs = match reqs.metadata().get("authorization") {
        Some(s)=>{
            let token = s.to_str().unwrap();
            wd_log::log_info_ln!("token:{}",token);
            reqs
        }
        None=>{return Err(Status::new(Code::PermissionDenied,"token is null"))}
    };
    match reqs.metadata().get("request_id") {
        Some(s)=>{
            let rid = s.to_str().unwrap();
            wd_log::log_info_ln!("request_id:{}",rid);
            Ok(reqs)
        }
        None=> Err(Status::new(Code::DataLoss,"request_id in null"))
    }
}